package com.culture.bootdemo.controller;


import com.culture.bootdemo.common.basevo.Result;
import com.culture.bootdemo.utils.RedisDao;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author ：wen
 * @date ：Created in 2019/8/5 16:42
 * @description：:
 */
@RestController
@RequestMapping("/redis")
@Slf4j
public class RedisController {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private RedisDao redisDao;

    @GetMapping("test")
    public void test() {
        for (int i = 1; i < 1_0002; i++) {
            redisTemplate.opsForValue().set("test_keys_" + i, i, 60 * 10, TimeUnit.SECONDS);
        }
    }


    /**
     * redis 批量操作
     */
    @GetMapping("testBatch")
    public void testBatch() {
        // 使用 executePipelined 执行批量操作
        List<Object> results = redisTemplate.executePipelined(new SessionCallback<Object>() {
            @Override
            public Object execute(@NotNull RedisOperations operations) {
                // 开始执行批量操作
                for (int i = 0; i < 10; i++) {
                    operations.opsForValue().set("pipelineKey" + i, "pipelineValue" + i);
                }
                return null; // 必须返回 null，否则不会执行 pipeline
            }
        });
    }

    /**
     * keys 方法 模糊匹配key
     */
    @GetMapping("test1")
    public void test1() {
        long l = System.currentTimeMillis();
        Set<String> keys = redisTemplate.keys("test_keys*");
        log.info("结束耗时:{}ms,个数:{}", (System.currentTimeMillis() - l), keys.size());
    }

    /**
     * scan 方法 模糊匹配key
     */
    @GetMapping("test2")
    public void test2() {
        long start = System.currentTimeMillis();
        //需要匹配的key
        String patternKey = "test_keys*";
        ScanOptions options = ScanOptions.scanOptions()
                .count(10000) //这里指定每次扫描key的数量
                .match(patternKey).build();
        RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
        Cursor cursor = redisTemplate.executeWithStickyConnection(redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
        List<String> result = new ArrayList<>();
        while (cursor.hasNext()) {
            result.add(cursor.next().toString());
        }
        //切记这里一定要关闭，否则会耗尽连接数。
        try {
            cursor.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("scan扫描共耗时：{} ms key数量：{}", System.currentTimeMillis() - start, result.size());

    }

    @GetMapping("hello")
    public Result hello() {

        redisTemplate.opsForHash().put("123456", "CURRENT_USER_ID", "userId");

        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        redisTemplate.opsForValue().multiSet(map);

        //设置锁
        //若redis有该值，则返回false，无，则返回true
        Boolean b = redisTemplate.opsForValue().setIfAbsent("key", "value");
        return Result.builder().build();
    }

    @GetMapping("hashtest")
    public Result hashtest() {

        redisTemplate.opsForSet().add("LOCAL_REDIS_USERID", 12131241223423233L);
        redisTemplate.opsForSet().add("LOCAL_REDIS_USERID", 222222222222222222L);
        Set<Object> set = new HashSet<>();
        set.add("1223");
        set.add("125");
        set.add("127");
        redisTemplate.opsForSet().add("sss", set);
        return Result.builder().build();
    }

    @Autowired
    private StringRedisTemplate template;
    private int m = 0;

    @RequestMapping("publish")
    public String publish() {
        int index = m;
        template.convertAndSend("mytopic2", "这是我发第1条的消息啊");
        /*for(int i=m;i<index+10;i++){
            template.convertAndSend("mytopic", "这是我发第"+i+"条的消息啊");
        }*/
        return "结束";
    }


    /**
     * 取两个数之间范围内的随机数
     *
     * @param start
     * @param end
     * @return
     */
    public static int getRandom(int start, int end) {
        return (int) (Math.random() * (end - start) + start);
    }

    /**
     * bitmap结构--实现签到功能
     */
    @GetMapping("sign")
    public void sign() {
        String key = "sign:20200713";
        // 该字段表示用户id:1-10000，假设有1w个用户，那么偏移量就是0-9999,依次记录着1w名用户
        long offSet = 324;
        Boolean aBoolean = redisDao.setBit(key, offSet, true);
        System.out.println(aBoolean);
    }
}
